package com.mxx.common.netty.ws;

import com.mxx.common.conv.JacksonConverter;
import com.mxx.common.exception.UnsupportedException;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import lombok.extern.slf4j.Slf4j;

/**
 * @Auther: Mr. Zeng
 * @Date: 2020/7/15 14:34
 * @Description: WebSocket 请求
 */
@Slf4j
public class DefaultNettyWebsocketRequest implements NettyWebsocketRequest {
    /**
     * 通道处理上下文
     */
    private ChannelHandlerContext channelHandlerContext;
    /**
     * WebSocket 请求数据模板
     */
    private WebSocketFrame webSocketFrame;
    /**
     * jackson转换器
     */
    private JacksonConverter jacksonConverter;
    /**
     * WebSocket 请求消息
     */
    private NettyWebsocketMessage nettyWebsocketMessage;
    /**
     * 通道ID
     */
    private String channelId;

    public DefaultNettyWebsocketRequest(ChannelHandlerContext channelHandlerContext, WebSocketFrame webSocketFrame, Class<? extends NettyWebsocketMessage> classes, JacksonConverter jacksonConverter) {
        this.channelHandlerContext = channelHandlerContext;
        this.webSocketFrame = webSocketFrame;
        this.jacksonConverter = jacksonConverter;
        this.channelId = channelHandlerContext.channel().id().asShortText();
        try {
            String textWebSocketFrame = ((TextWebSocketFrame) webSocketFrame).text();
            nettyWebsocketMessage = jacksonConverter.readValue(textWebSocketFrame, classes);
            if (nettyWebsocketMessage.failure()) {
                throw new UnsupportedException("unsupported request , method is empty or type is fail");
            }
        } catch (UnsupportedException ex) {
            throw new RuntimeException(ex.getMessage());
        }
    }

    @Override
    public NettyWebsocketMessage getNettyWebsocketMessage() {
        return nettyWebsocketMessage;
    }

    @Override
    public WebSocketFrame getWebSocketFrame() {
        return webSocketFrame;
    }

    /**
     * 发送消息给自己
     *
     * @param data 数据
     */

    @Override
    public void sendSelf(Object data) {
        NettyChannelSupervise.sendOfChannel(channelHandlerContext.channel(), this.convert(data));
    }

    /**
     * 发送给指定的通道
     *
     * @param data      数据
     * @param channelId 通道ID
     */

    @Override
    public void sendOfChannelId(Object data, String... channelId) {
        if (channelId.length == 0) {
            return;
        }
        TextWebSocketFrame content = this.convert(data);
        for (int i = 0; i < channelId.length; i++) {
            NettyChannelSupervise.sendOfChannel(channelId[i], content);
        }
    }

    /**
     * 发送给指定的通道
     *
     * @param data      数据
     * @param channelId 通道ID
     */

    @Override
    public boolean sendOfChannelId(Object data, String channelId) {
        TextWebSocketFrame content = this.convert(data);
        return NettyChannelSupervise.sendOfChannel(channelId, content);
    }

    /**
     * 广播消息
     *
     * @param data 数据
     */

    @Override
    public void sendAll(Object data) {
        TextWebSocketFrame content = this.convert(data);
        NettyChannelSupervise.sendAll(channelHandlerContext.channel(), content);
    }

    /**
     * @return 获取通上下文
     */

    @Override
    public ChannelHandlerContext getChannelHandlerContext() {
        return channelHandlerContext;
    }

    /**
     * 获取通道ID
     *
     * @return
     */

    @Override
    public String getChannelId() {
        return channelId;
    }

    /**
     * 消息转换
     *
     * @param data
     * @return
     */

    public TextWebSocketFrame convert(Object data) {
        return new TextWebSocketFrame(jacksonConverter.writeValueAsString(data));
    }

}
